package an.qt5.javagather;

import java.io.IOException;
import tw.com.prolific.pl2303multilib.PL2303MultiLib;
import android.os.Bundle;
import android.os.Handler;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import java.io.UnsupportedEncodingException;
import android.app.PendingIntent;
//min and max
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import java.util.List;
import java.util.ArrayList;
import android.util.Log;
import java.lang.Thread.UncaughtExceptionHandler;

import java.util.HashMap;
import java.util.Iterator;
import android.hardware.usb.UsbDevice;
import java.lang.String;

import java.util.HashMap;
import java.util.Iterator;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.IBinder;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.content.pm.PackageManager.NameNotFoundException;


class UARTSettingInfo {
        public int iPortIndex = 0;
        public PL2303MultiLib.BaudRate mBaudrate = PL2303MultiLib.BaudRate.B9600;
        public PL2303MultiLib.DataBits mDataBits = PL2303MultiLib.DataBits.D8;
        public PL2303MultiLib.Parity mParity = PL2303MultiLib.Parity.NONE;
        public PL2303MultiLib.StopBits mStopBits = PL2303MultiLib.StopBits.S1;
        public PL2303MultiLib.FlowControl mFlowControl = PL2303MultiLib.FlowControl.OFF;
}//class UARTSettingInfo

public class PL2303HXDSerialPort extends org.qtproject.qt5.android.bindings.QtActivity {
//public class PL2303HXDSerialPort extends Activity{
    private static PL2303MultiLib mSerialMulti;
    private static final int MAX_DEVICE_COUNT = 4;
    private static final String ACTION_USB_PERMISSION = "an.qt5.javagather.USB_PERMISSION";
    private static UARTSettingInfo gUARTInfoList[];
    private static boolean gThreadStop[] = new boolean[MAX_DEVICE_COUNT];
    private static boolean gRunningReadThread[] = new boolean[MAX_DEVICE_COUNT];
//    private static boolean bDeviceOpened[] = new boolean[MAX_DEVICE_COUNT];
    private static final int ReadDataBufferSize = 256;
    private static boolean registerflag = false;

    private static final int DeviceIndex1 = 0;
    private static final int DeviceIndex2 = 1;
    private static final int DeviceIndex3 = 2;
    private static final int DeviceIndex4 = 3;

    private static int readCount = 1;
    private static int readSleep = 100;

//    private static String TAG = "PL2303HXD_Gather_Log";
    private static PL2303HXDSerialPort m_instance;

    public PL2303HXDSerialPort(){
        m_instance = this;
    }
//    //min
//    public static void mini()
//    {
//        m_instance.moveTaskToBack(true);
//    }
//    //max
//    public static void moveTaskToFrount(){
//        if(!m_instance.isForeground(m_instance.getPackageName()))
//        {
//            ActivityManager am = (ActivityManager)m_instance.getSystemService(Context.ACTIVITY_SERVICE);
//            am.moveTaskToFront(m_instance.getTaskId(),0);
//        }
//    }
//    private boolean isForeground(String packageName){
//        ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
//        List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
//        if (appProcesses == null)
//            return false;
//        for (RunningAppProcessInfo appProcess : appProcesses) {
//            // The name of the process that this object is associated with.
//            if (appProcess.processName.equals(packageName)
//                    && appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
//                return true;
//            }
//        }
//        return false;
//    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
          Thread.setDefaultUncaughtExceptionHandler(restartHandler); // 程序崩溃时触发线程  以下用来捕获程序崩溃异常
//          registerUSB();//
          UsbInit();
    }
    // 创建服务用于捕获崩溃异常
    private UncaughtExceptionHandler restartHandler = new UncaughtExceptionHandler() {
        public void uncaughtException(Thread thread, Throwable ex) {
            //发生崩溃异常时,重启应用
            Intent intent_ = new Intent("an.qt5.javagather.exception");
            sendBroadcast(intent_);
        }
    };
    private void UsbInit()
    {
        UsbInitPermission(1);
        try {
        Thread.sleep(100);
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
        UsbInitPermission(2);
        try {
        Thread.sleep(100);
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
        UsbInitPermission(3);
        try {
        Thread.sleep(100);
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
        UsbInitPermission(4);
        try {
        Thread.sleep(100);
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
    }

    static final String YOUR_APP_PACKAGE_NAMESPACE = "an.qt5.javagather";
    static final String ACTION_USB_PERMISSION_APP =  "ACTION_USB_PERMISSION_ISSUER";
    private void UsbInitPermission(int id)
    {
        Intent intent_usb = new Intent();
        intent_usb.setAction(ACTION_USB_PERMISSION_APP);
        intent_usb.putExtra("packageName", YOUR_APP_PACKAGE_NAMESPACE);
         //device_filter.xml里的字段
        intent_usb.putExtra("vendorId", 1659);
        switch(id)
        {
        case 1:
        intent_usb.putExtra("productId", 8963);
        break;
        case 2:
        intent_usb.putExtra("productId", 9553);
        break;
        case 3:
        intent_usb.putExtra("productId", 8964);
        break;
        case 4:
        intent_usb.putExtra("productId", 9475);
        break;
        }
        //发送广播
        sendBroadcast(intent_usb);
    }

//    private UsbManager mUsbManager;
//    private void registerUSB()
//    {
//        mUsbManager = (UsbManager) m_instance.getSystemService(Context.USB_SERVICE);
//        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
////        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
////        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
//        registerReceiver(mUsbReceiver, filter);
//    }

//    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
//        public void onReceive(Context context, Intent intent) {
//            String action = intent.getAction();
//            if (ACTION_USB_PERMISSION.equals(action)) {
//                PL2303HXDNative.OnNotify_LOG("授权:UsbForPl2303Permission");
//                synchronized (this) {
//                    UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
//                    if(device != null && device.getVendorId() == 1659){
//                        if(!mUsbManager.hasPermission(device))
//                        {
////                            if(SystemManager.isRoot()){
////                                PL2303HXDNative.OnNotify_LOG("root for app!");
////                                String apkRoot="chmod 777 "+getPackageCodePath();
////                                SystemManager.RootCommand(apkRoot);
////                            }
//                            PL2303HXDNative.OnNotify_LOG("USB requestPermission!");
//                            Intent intent_usb = new Intent();
//                            intent_usb.setAction("ACTION_USB_PERMISSION_ISSUER");
//                            intent_usb.putExtra("packageName", getPackageName());
//                            intent_usb.putExtra("vendorId", device.getVendorId());
//                            intent_usb.putExtra("productId", device.getProductId());
//                            //发送广播
//                            sendBroadcast(intent_usb);
//                        }
//                    }
//                }
//            }
//        }
//    };


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //super.onSaveInstanceState(outState);
    }
    private static int PLCInit(){
        PL2303HXDNative.OnNotify_LOG("pl2303 get service");
        int ret = PL2303Init();
        if(1==ret){
//            m_instance.registerUSB();
            m_instance.registerSerialMulti();
        }
        PL2303HXDNative.OnNotify_LOG("Leave  PLCInit ");
        return ret;
    }
    private static int PL2303Init(){
        try{
            // get service
            mSerialMulti = new PL2303MultiLib((UsbManager) m_instance.getSystemService(Context.USB_SERVICE),
                    m_instance, ACTION_USB_PERMISSION);
//            if you don't want to use Software Queue, below constructor to be used
//            mSerialMulti = new PL2303MultiLib((UsbManager) m_instance.getSystemService(Context.USB_SERVICE),
//                m_instance, ACTION_USB_PERMISSION,false);
        }catch (Exception e) {
            e.printStackTrace();
            PL2303HXDNative.OnNotify_LOG("pl2303 get service Exception:"+e.toString());
            mSerialMulti = null;
            return 0;
        }
        try{
            gUARTInfoList = new UARTSettingInfo[MAX_DEVICE_COUNT];

            for(int i=0;i<MAX_DEVICE_COUNT;i++) {
                gUARTInfoList[i] = new UARTSettingInfo();
                gUARTInfoList[i].iPortIndex = i;
                gThreadStop[i] = false;
                gRunningReadThread[i] = false;
//                bDeviceOpened[i] = false;
            }
        }catch (Exception e) {
            e.printStackTrace();
            PL2303HXDNative.OnNotify_LOG("pl2303 init UARTINfo Exception:"+e.toString());
            mSerialMulti = null;
            return 0;
        }
        return 1;
    }

    private static int OpenUARTDevice(int index,int baudrate,int readCount_,int readSleep_) {
//        PL2303HXDNative.OnNotify_LOG("Enter OpenUARTDevice: "+String.valueOf(index));

        if(mSerialMulti==null) {
            if(0==PLCInit()){
                PL2303HXDNative.OnNotify_LOG("Error: mSerialMulti==null");
                return 2;
            }
        }
        if(!mSerialMulti.PL2303IsDeviceConnectedByIndex(index)) {
//            PL2303HXDNative.OnNotify_LOG("Error: !AP_mSerialMulti.PL2303IsDeviceConnectedByIndex "+String.valueOf(index));
//            UsbResume();
            return 3;
        }
        boolean res;
        UARTSettingInfo info = gUARTInfoList[index];
        switch(baudrate){
            case 1200:
            info.mBaudrate = PL2303MultiLib.BaudRate.B1200;
            break;
            case 2400:
            info.mBaudrate = PL2303MultiLib.BaudRate.B2400;
            break;
            case 4800:
            info.mBaudrate = PL2303MultiLib.BaudRate.B4800;
            break;
            case 9600:
            info.mBaudrate = PL2303MultiLib.BaudRate.B9600;
            break;
            case 19200:
            info.mBaudrate = PL2303MultiLib.BaudRate.B19200;
            break;
            case 38400:
            info.mBaudrate = PL2303MultiLib.BaudRate.B38400;
            break;
            case 57600:
            info.mBaudrate = PL2303MultiLib.BaudRate.B57600;
            break;
            case 115200:
            info.mBaudrate = PL2303MultiLib.BaudRate.B115200;
            break;
            default:
            PL2303HXDNative.OnNotify_LOG("Error: baudrate is not standard ,fail to PL2303OpenDevByUARTSetting");
            return 5;
        }
        PL2303HXDNative.OnNotify_LOG("UARTSettingInfo: index:"+String.valueOf(info.iPortIndex));
        res = mSerialMulti.PL2303OpenDevByUARTSetting(index, info.mBaudrate, info.mDataBits, info.mStopBits,
            info.mParity, info.mFlowControl);
        if( !res ) {
            PL2303HXDNative.OnNotify_LOG("Error: fail to PL2303OpenDevByUARTSetting");
            return 4;
        }

//        bDeviceOpened[index] = true;

        if(!gRunningReadThread[index]) {
            UpdateDisplay(index);
        }
        readCount = readCount_;
        readSleep = readSleep_;
        PL2303HXDNative.OnNotify_LOG("Open ["+ mSerialMulti.PL2303getDevicePathByIndex(index) +"] successfully!");
        return 1;
    }//private void OpenUARTDevice(int index)

    private static void UpdateDisplay(int index) {
        gThreadStop[index] = false;
        gRunningReadThread[index] = true;

        if( DeviceIndex1==index ) {
            new Thread(ReadLoop1).start();
        } else if( DeviceIndex2==index ) {
            new Thread(ReadLoop2).start();
        } else if( DeviceIndex3==index ) {
            new Thread(ReadLoop3).start();
        }else if( DeviceIndex4==index ){
            new Thread(ReadLoop4).start();
        }else{
            PL2303HXDNative.OnNotify_LOG("closeUARTDevicel:"+String.valueOf(index));
        }
    }

    public static void closeUARTDevicel(int index){
        PL2303HXDNative.OnNotify_LOG("index is out [0,3]");
        if(null!=mSerialMulti){
            gThreadStop[index] = true;
//            gRunningReadThread[index] = false;
//            bDeviceOpened[index] = false;
        }
    }

    /**
    * 十六进制串转化为byte数组
    *
    * @return the array of byte
    */
    public static final byte[] hex2byte(String hex)
        throws IllegalArgumentException {
        if (hex.length() % 2 != 0) {
            throw new IllegalArgumentException();
        }
        char[] arr = hex.toCharArray();
        byte[] b = new byte[hex.length() / 2];
        for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
            String swap = "" + arr[i++] + arr[i];
            int byteint = Integer.parseInt(swap, 16) & 0xFF;
            b[j] = new Integer(byteint).byteValue();
        }
        return b;
    }
    /**
    * 字节数组转换为十六进制字符串
    *
    * @param b
    *            byte[] 需要转换的字节数组
    * @return String 十六进制字符串
    */
    public static final String byte2hex(byte b[],int realLength) {
        if (b == null) {
            throw new IllegalArgumentException(
                "Argument b ( byte array ) is null! ");
        }
        String stmp = "";
        StringBuilder sbHex=new StringBuilder();
        for (int n = 0; n < realLength; n++) {
            stmp = Integer.toHexString(b[n] & 0x000000FF);
            if (stmp.length() == 1) {
                sbHex.append("0");
                sbHex.append(stmp);
            } else if(stmp.length() == 2) {
                sbHex.append(stmp);
            }else{
                PL2303HXDNative.OnNotify_LOG("byte2hex : " + stmp.length());
            }
        }
        return sbHex.toString().toUpperCase();
    }

    private static int WriteToUARTDevice(int index,String strWrite) {
//        PL2303HXDNative.OnNotify_LOG(String.valueOf(index)+" Enter WriteToUARTDevice");
        if(mSerialMulti==null)
        {
            PL2303HXDNative.OnNotify_LOG(String.valueOf(index)+" WriteToUARTDevice fail,mSerialMulti=null");
            return -1;
        }

        if(!mSerialMulti.PL2303IsDeviceConnectedByIndex(index)){
            PL2303HXDNative.OnNotify_LOG(String.valueOf(index)+" WriteToUARTDevice fail,mSerialMulti is unconect");
            return -2;
        }

        if( strWrite==null || "".equals(strWrite.trim()) ) { //str is empty
            PL2303HXDNative.OnNotify_LOG(String.valueOf(index)+" WriteToUARTDevice: no data to write");
            return -3;
        }
//        PL2303HXDNative.OnNotify_LOG(String.valueOf(index)+" PL2303Multi Write(" + strWrite.length() + "):" + strWrite);
        int res = 0;
        try{
            res = mSerialMulti.PL2303Write(index, hex2byte(strWrite.trim()));
        }catch(Exception e){
            PL2303HXDNative.OnNotify_LOG("UnsupportedEncodingException");
            return -4;
        }
        if( res<0 ) {
            PL2303HXDNative.OnNotify_LOG(index+"w: fail to write: "+ res);
            return -5;
        }
        return res;
//        PL2303HXDNative.OnNotify_LOG(String.valueOf(index)+" Leave WriteToUARTDevice");
    } //private void WriteToUARTDevice(int index)

    @Override
    protected void onStart() {
        super.onStart();
        m_instance.registerSerialMulti();
    }
    @Override
    protected void onRestart() {
        super.onRestart();
        m_instance.registerSerialMulti();
    }
    @Override
    protected void onResume() {
        super.onResume();
//        m_instance.UsbResume();
        m_instance.registerSerialMulti();
    }//public void onResume()

    @Override
    protected void onPause() {
//        m_instance.unRegisterSerialMulti();
        super.onStart();
        m_instance.registerSerialMulti();
    }
    @Override
    protected void onStop() {
        super.onStop();
        m_instance.registerSerialMulti();
    }
    @Override
    protected void onDestroy() {
        m_instance.unRegisterSerialMulti(true);
//        Intent intent = new Intent("an.qt5.javagather.destroy");
//        sendBroadcast(intent);
        super.onDestroy();
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

    private void registerSerialMulti()
    {
        if(registerflag)
            return;

//        if(mSerialMulti==null) {
//            int ret = PL2303Init();
//            if(1!=ret)
//                return;
//        }
        if(mSerialMulti!=null) {
            int iDeviceCount = mSerialMulti.PL2303Enumerate();
            PL2303HXDNative.OnNotify_LOG("onResume for mSerialMulti iDeviceCount="+String.valueOf(iDeviceCount));
            if(0!=iDeviceCount){
                //register receiver for PL2303Multi_USB notification
                IntentFilter filter = new IntentFilter();
                //usb
                filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
                filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
//                filter.addAction(ACTION_USB_PERMISSION);
//                filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
//                filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
                //msg
                filter.addAction(mSerialMulti.PLUART_MESSAGE);
                registerReceiver(PLMultiLibReceiver, filter);
                //register
                registerflag = true;
            }
        }
    }

    private void unRegisterSerialMulti(boolean destroyflag){
        if(mSerialMulti!=null) {
            for(int i=0;i<MAX_DEVICE_COUNT;i++) {
                gThreadStop[i] = true;
            }//First to stop app view-thread
            if(mSerialMulti.PL2303Enumerate()>0){
                unregisterReceiver(PLMultiLibReceiver);
                registerflag = false;
            }
            mSerialMulti.PL2303Release();
            if(destroyflag){
                mSerialMulti = null;
            }
        }
    }
//    static final String ACTION_USB_DEVICE_PERMISSION = "an.qt5.javagather.USB_PERMISSION";
    private final BroadcastReceiver PLMultiLibReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction().equals(mSerialMulti.PLUART_MESSAGE)){
               PL2303HXDNative.OnNotify_LOG("USB PLUART_MESSAGE 信号");
               Bundle extras = intent.getExtras();
               if(extras!=null) {
                   String str = (String)extras.get(mSerialMulti.PLUART_DETACHED);
//                   DumpMsg("receive data:"+str);
                   int index = Integer.valueOf(str);
                   if(DeviceIndex1==index
                    ||DeviceIndex2==index
                    ||DeviceIndex3==index
                    ||DeviceIndex4==index) {
                        gThreadStop[index] = true;
                   }
                }
            }
            if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
                PL2303HXDNative.OnNotify_LOG("静态广播接收器设备插入");
                boolean pl2303InsertFlag = false;
                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                PL2303HXDNative.OnNotify_LOG("\ndevice name: "+device.getDeviceName()+"\ndevice product name:"
                        +device.getProductName()+"\nvendor id:"+device.getVendorId()+
                        "\ndevice serial: "+device.getSerialNumber());
                if((device.getProductId() == 8963 || device.getProductId() == 9553
                        || device.getProductId() == 8964 || device.getProductId() == 9475 )
                    && device.getVendorId() == 1659) {
                        //do your work
                        PL2303HXDNative.OnNotify_LOG("device "+device.getDeviceName()+" hasPermission!");
                        pl2303InsertFlag = true;
                }
                if(pl2303InsertFlag){
                    Intent intent_ = new Intent("an.qt5.javagather.restart");
                    sendBroadcast(intent_);
                }
            }
            else{
                ;
            }
        }//onReceive
    };

private static void DelayTime(int dwTimeMS) {
    //Thread.yield();
    long StartTime, CheckTime;

    if(0==dwTimeMS) {
        Thread.yield();
        return;
    }
    //Returns milliseconds running in the current thread
    StartTime = System.currentTimeMillis();
    do {
        CheckTime=System.currentTimeMillis();
        Thread.yield();
     } while( (CheckTime-StartTime)<=dwTimeMS);
}

private static int ReadLen1;
private static byte[] ReadBuf1 = new byte[ReadDataBufferSize];
private static Handler mHandler1 = new Handler();
private static Runnable ReadLoop1 = new Runnable() {
    public void run() {
        for (;;) {
            ReadLen1 = mSerialMulti.PL2303Read(DeviceIndex1, ReadBuf1);
            if (ReadLen1 > 0) {
                //ReadBuf1[ReadLen1] = 0;
//                PL2303HXDNative.OnNotify_LOG("Read 1 Length : " + ReadLen1);
                mHandler1.post(new Runnable() {
                    public void run() {
                        String readBuf = byte2hex(ReadBuf1,ReadLen1);
                        PL2303HXDNative.OnNotify_MSG(DeviceIndex1,readBuf);
                    }//run
                });//Handler.post
            }//if (len > 0)
//            PL2303HXDNative.OnNotify_LOG("Read Index(1) readSleep: "+readSleep);
            DelayTime(readSleep);
            if (gThreadStop[DeviceIndex1]) {
                gRunningReadThread[DeviceIndex1] = false;
                return;
            }//if
        }//for(...)
    }//run
};//Runnable

private static int ReadLen2;
private static byte[] ReadBuf2 = new byte[ReadDataBufferSize];
private static Handler mHandler2 = new Handler();
private static Runnable ReadLoop2 = new Runnable() {
    public void run() {

        for (;;) {
            ReadLen2 = mSerialMulti.PL2303Read(DeviceIndex2, ReadBuf2);
            if (ReadLen2 > 0) {
                //ReadBuf2[ReadLen2] = 0;
                PL2303HXDNative.OnNotify_LOG("Read 2 Length : " + ReadLen2);
                mHandler2.post(new Runnable() {
                    public void run() {
                        String readBuf = byte2hex(ReadBuf2,ReadLen2);
                        PL2303HXDNative.OnNotify_MSG(DeviceIndex1,readBuf);
                    }//run
                });//Handler.post
            }//if (len > 0)

            DelayTime(readSleep);

            if (gThreadStop[DeviceIndex2]) {
                gRunningReadThread[DeviceIndex2] = false;
                return;
            }//if
        }//for(...)
    }//run
};//Runnable

private static int ReadLen3;
private static byte[] ReadBuf3 = new byte[ReadDataBufferSize];
private static Handler mHandler3 = new Handler();
private static Runnable ReadLoop3 = new Runnable() {
    public void run() {
        for (;;) {
            ReadLen3 = mSerialMulti.PL2303Read(DeviceIndex3, ReadBuf3);
            if (ReadLen3 > 0) {
                //ReadBuf3[ReadLen3] = 0;
                PL2303HXDNative.OnNotify_LOG("Read 3 Length : " + ReadLen3);
//                    String readBuf = byte2hex(ReadBuf3,ReadLen3);
//                    PL2303HXDNative.OnNotify_MSG(1,readBuf);
                mHandler3.post(new Runnable() {
                    public void run() {
                        String readBuf = byte2hex(ReadBuf3,ReadLen3);
                        PL2303HXDNative.OnNotify_MSG(DeviceIndex1,readBuf);
                    }//run
                });//Handler.post
            }//if (len > 0)

            DelayTime(readSleep);

            if (gThreadStop[DeviceIndex3]) {
                gRunningReadThread[DeviceIndex3] = false;
                return;
            }//if
        }//for(...)
    }//run
};//Runnable

private static int ReadLen4;
private static byte[] ReadBuf4 = new byte[ReadDataBufferSize];
private static Handler mHandler4 = new Handler();
private static Runnable ReadLoop4 = new Runnable() {
    public void run() {
        for (;;) {
            ReadLen4 = mSerialMulti.PL2303Read(DeviceIndex4, ReadBuf4);
            if (ReadLen4 > 0) {
                //ReadBuf4[ReadLen4] = 0;
                PL2303HXDNative.OnNotify_LOG("Read 4 Length : " + ReadLen4);
                mHandler4.post(new Runnable() {
                    public void run() {
                        String readBuf = byte2hex(ReadBuf4,ReadLen4);
                        PL2303HXDNative.OnNotify_MSG(DeviceIndex1,readBuf);
                    }//run
                });//Handler.post
            }//if (len > 0)

            DelayTime(readSleep);

            if (gThreadStop[DeviceIndex4]) {
                gRunningReadThread[DeviceIndex4] = false;
                return;
            }//if
        }//for(...)
    }//run
};//Runnable

}
